
	/***********************************************************************************************
		
		Factory: Error
		
			e			jsl.Error				()																-	sid: 4.0
			e			jsl.Error				(msg		, cause*)								
			e			jsl.Error				(e			, cause*)						
			e			jsl.Error				(msg		, params, cause*)	
				
		Methods:
			msg		getMessage			()																- sid: 4.0
			e			getCause				()																- sid: 4.0
      st    getStackTrace   ()																- sid: 4.0
      n     getLineNumber   ()																- sid: 4.0
      n     getCharNumber   ()																- sid: 4.0
      name  getScriptName   ()																- sid: 4.0
      data	getData					(id)															- sid: 4.0

      e   	setMessage      (msg, params*)										- sid: 4.0
      cause	setCause        (cause)														- sid: 4.0
			e			setLineNumber		(n)																- sid: 4.0
			e			setCharNumber		(n)																- sid: 4.0
			e			setScriptName		(name)														- sid: 4.0
			e			setData					(id, value)												- sid: 4.0
			
      e   	setLine         (line, character*)								- sid: 4.0
      e   	setScript    	 	(script, line*, character*)				- sid: 4.0
      	
      e   	trace           (cx, args*)												- sid: 4.0
      e   clearStackTrace 	()																- sid: 4.0

		Overriding:
			s			toString				(small*)													- sid: 4.0
			
		Sys:
			@sys: Safari 4.0.4 									- e = new SyntaxError -> e.message = SyntaxError instead of '' as Firefox and other
			@sys:	Konqueror 4.4.00 (KDE 4.4.0) 	- with debug active show an error message every time is called an Error 
																						constructor	
			
	************************************************************************************************/
				
	//-------------------------------------------------------------------------------
	jsl.Error = function(p1, p2, p3) {
		try {
			var proto, rv, id
			//@d[						
			if(arguments.length > (jsl.isArray(p2) ? 3 : 2)) 	throw jsl.ParamError()			
			if(arguments.length 			&& p1 == null)					throw jsl.ParamError("NullValue:msg")						
			if(arguments.length >= 2	&& p2 == null)					throw jsl.ParamError("NullValue:" + (jsl.isArray(p2) ? "params" : "cause"))							
			if(arguments.length == 3 	&& p3 == null)					throw jsl.ParamError("NullValue:cause")
			if(jsl.isArray(p2) 				&& jsl.isError(p1))			throw jsl.ParamError("BadType:msg:!Error")
			//@d]
			
			//1° - no params
			//@sys:	Safari 5.0.3 - create an error object without a message set a default message = 'Unknown error'								
			if(!arguments.length)	
				rv = new Error("")

			//2° - bypass
			else if(jsl.isError(p1) && p1.__augmented)	{			
				if(arguments.length === 2) 	p1.setCause(p2)				
				return p1
			}
			
			//3° - native error
			else if(jsl.isError(p1)) {
				if(arguments.length === 2)	jsl.Error.setCause(p1, p2)		
				rv = p1
			}
											
			//4° - message with explicit parameters
			else if(jsl.isArray(p2)) {				
												
				rv = new Error(p1)	
				jsl.Error.setMessage(rv, p1, p2)
				if(arguments.length === 3) jsl.Error.setCause(rv, p3)		
			}
		
			//5° - message
			else {				
				rv = new Error(p1)					
				jsl.Error.setMessage(rv, p1)
 				if(arguments.length === 2)	jsl.Error.setCause(rv, p2)																
			}

			proto = jsl.Error.prototype
			
    	for(id in proto)
    		if(proto.hasOwnProperty(id))
					rv[id] = proto[id]
			
			//@sys: Explorer 8.0.6 - the toString method is always not enumerable also if it is set
			rv.toString = proto.toString
			
    	return rv	    			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Error.__name 		= "jsl.Error"
	//-------------------------------------------------------------------------------
	jsl.Error.prototype = jsl.Object()	
	//-------------------------------------------------------------------------------
	jsl.Error.prototype.getMessage 	= function() {
  	try {//@d[
			if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")  	
  		if(arguments.length) 		throw jsl.ParamError()//@d]
			
			//@sys: Explorer 8.0.6 - Error(is, message) - >take two parameters, the first is the error code and the second is
			//the error message. If the first parameter is not convertible into number and the second is not passed, 
			//it is considered as description. 
  		return this.__message || this.__dmessage || this.message || this.description || ""
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
  //-------------------------------------------------------------------------------
  jsl.Error.prototype.getCause = function() {
    try {//@d[
			if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")  	    
      if(arguments.length) 		throw jsl.ParamError()//@d]
			
      return this.__cause || null
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
  jsl.Error.prototype.getStackTrace = function() {
    try {
      var trace, len
      //@d[
			if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")  	
      if(arguments.length) 		throw jsl.ParamError()//@d]
			
			len	= this.__st ? this.__st.length : 0
			
      for(var a = 0, st = []; a < len; a++) {
       
			  trace = this.__st[a]
       
			  st.push({ 
									obj:			trace.obj							,
									method:		trace.method					,
                  context: 	trace.context       	, 
                  params: 	trace.params.slice()	, 
                  values:		trace.values.slice() 
                })
      }

      return st
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
  jsl.Error.prototype.getLineNumber = function() {
    try {//@d[
			if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")  	    
      if(arguments.length) 		throw jsl.ParamError()//@d]
			
      return this.__line || (jsl.__ni_error_lineNumber && jsl.__ni_error_lineNumber(this)) || null
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
  jsl.Error.prototype.getCharNumber = function() {
    try {//@d[
			if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")  	    
      if(arguments.length) 		throw jsl.ParamError()//@d]
			
      return this.__character	|| (jsl.__ni_error_charNumber && jsl.__ni_error_charNumber(this)) || null
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
  jsl.Error.prototype.getScriptName = function() {
    try {//@d[
			if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")  	    
      if(arguments.length) 		throw jsl.ParamError()//@d]
			
      return this.__script || (jsl.__ni_error_scriptName && jsl.__ni_error_scriptName(this)) || null
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
  jsl.Error.prototype.getData = function(id) {
    try {//@d[
			if(!jsl.isError(this))			throw jsl.TypeError("BadMethodCall:Error")  	    
      if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(id, "s+", "id")//@d]
			
			return this.__data && this.__data.hasOwnProperty(id) ? this.__data[id] : null						
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
	//-------------------------------------------------------------------------------
	jsl.Error.prototype.setMessage = function(msg, params) {
  	try {
			var id, ps, m
			//@d[
			if(!jsl.isError(this))												throw jsl.TypeError("BadMethodCall:Error")  				
  		if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()  		
			if(msg == null)																throw jsl.ParamError("NullValue:msg")	
			
			if(arguments.length === 2)	jsl.validate(params, "a", "params")//@d]

			//the array of the match with final asterisc is never null
			m		= msg + ""
			id 	= m.match(/^[^\:]*/)[0]
			
			if(!m || m === ":")										throw jsl.ParamError("EmptyString:msg")	
			if(id === "def" && !this.__dmessage)	throw jsl.ParamError("BadValue:		msg(id):id != 'def'")
			
			if(!params) {
			
				ps = m.split(":").slice(1)						

				for(var a = 0, l = ps.length; a < l; a += 1) {							

					if(ps[a].slice(-1) === "\\") {
						ps[a] = ps[a].slice(0, -1) + ":" + (ps[a + 1] || "")
						ps.splice(a + 1, 1)
						l--
					}
					
					ps[a] = ps[a].replace(/^\s*|\s*$/g, "")
				}
			}			
			else ps = params			
			
			//1° - default
			//2° - id message
			//3° - inline message with marker and explicit parameters
			//4° - inline message with explicit parameters
			//5° - inline message
			try {
				if(id === "def")																					m = jsl.compileMessage(this.__dmessage, ps)				
				else if(jsl.__msgs[id])																		m = jsl.compileMessage(id, ps)
				else if(arguments.length === 2 && m.charAt(0) === ":")		m = jsl.compileMessage(m.slice(1), ps)
				else if(arguments.length === 2)														m = jsl.compileMessage(m, ps)
				else if(m.charAt(0) === ":")															m = m.slice(1) 
			}			
			catch(e) 	{ 
				throw jsl.ParamError("BadArrayLength:params")	
			}
			
			this.__message = m
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setCause = function(cause) {
  	try {
  		var next
  		//@d[
			if(!jsl.isError(this))				throw jsl.TypeError("BadMethodCall:Error")  	
  		if(arguments.length !== 1)		throw jsl.ParamError()
			if(cause == null)							throw jsl.ParamError("NullValue:cause")
			if(this === cause)						throw jsl.ParamError("CircularReference:cause")
			
			next = jsl.Error(cause).getCause()
			
			while(next) {
				if(next === this)						throw jsl.ParamError("CircularReference:cause")		
				next = next.getCause()
			}//@d]
			
			this.__cause = jsl.Error(cause)
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setLineNumber = function(n) {
  	try {//@d[
			if(!jsl.isError(this))			throw jsl.TypeError("BadMethodCall:Error")  	
  		if(arguments.length !== 1) 	throw jsl.ParamError()			
			jsl.validate(n, "n++", "n")//@d]
			
  		this.__line = +n
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setCharNumber = function(n) {
  	try {//@d[
			if(!jsl.isError(this))			throw jsl.TypeError("BadMethodCall:Error")  	  	
  		if(arguments.length !== 1) 	throw jsl.ParamError()
			jsl.validate(n, "n++", "n")//@d]
			
  		this.__character = +n
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setScriptName = function(name) {
  	try {//@d[
			if(!jsl.isError(this))			throw jsl.TypeError("BadMethodCall:Error")  	
  		if(arguments.length !== 1) 	throw jsl.ParamError()
			jsl.validate(name, "s+", "name")//@d]
			
  		this.__script = name + ""
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setData = function(id, value) {
  	try {//@d[
			if(!jsl.isError(this))			throw jsl.TypeError("BadMethodCall:Error")  	
  		if(arguments.length !== 2) 	throw jsl.ParamError()
			jsl.validate(id, "s+", "id")//@d]
			
			if(!this.__data) this.__data = {}		
			this.__data[id] = value
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setLine = function(line, character) {
  	try {//@d[
			if(!jsl.isError(this))												throw jsl.TypeError("BadMethodCall:Error")  	
  		if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(line, "n++", "line")
			
			if(arguments.length === 2)										
				jsl.validate(character, "n++", "character")//@d]
				
			this.__line	= +line
  		if(character)	this.__character = +character
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.setScript = function(script, line, character) {
  	try {//@d[
  		if(!jsl.isError(this))												throw jsl.TypeError("BadMethodCall:Error")
  		if(!arguments.length || arguments.length > 3)	throw jsl.ParamError()

			jsl.validate(script, "s+", "script")

			if(arguments.length === 2)	jsl.validate(line			, "n++", "line")
			if(arguments.length === 3)	jsl.validate(character, "n++", "character")//@d]

			this.__script = script + ""
			
			if(line)			this.__line				= +line
  		if(character)	this.__character 	= +character
  		return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }
 	//-------------------------------------------------------------------------------
	jsl.Error.prototype.trace = function(cx, args) {
		try {
			var cname, fname, context, params
			//@d[
  		if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")//@d]
			
			//1° - String context
			//-----------------------------------------	
			
			//cx can be a String object with a method that has throwed an error.
			if(typeof cx === "string") {	
				//@d[
				if(arguments.length > 2)			throw jsl.ParamError()
				if(!cx.length)								throw jsl.ParamError("EmptyString:cx")
				if(arguments.length === 2) 		
					if(!jsl.isArrayLike(args))	throw jsl.ParamError("BadType:args:Array-like")//@d]
					
				context = cx			
				params	= []
								
				if(args && args.length) {
					
					params = cx.match(/^[\s\S]+\((\s*[a-zA-Z_$][\w$]*\s*(?:,\s*[a-zA-Z_$][\w$]*\s*)*)\)$/)
					//@d[
					if(!params)	throw jsl.ParamError("BadValue:cx")//@d]					

					params = params.length ? params[1].replace(/[\n\s]+/g, "").split(",") : []					
					
					//the values can be equal or more than formal parameters but not less
					if(params.length > args.length)	throw jsl.ParamError("BadArrayLength:args:" + params.length)
				}
			}
			//2° - Object context
			//-----------------------------------------	
			else {//@d[
				if(arguments.length !== 2)	throw jsl.ParamError()

				jsl.validate(cx						, "o"	, "cx")
				jsl.validate(args					, "al", "args")
				jsl.validate(args.callee	, "f", "args.callee")//@d]

				cname = cx === jsl.__context ? "" : jsl.Object.getOid(cx) || jsl.Object.getName(cx)
								
				for(var id in cx)
					if(cx[id] === args.callee) {
						fname = id
						break
					}

				if(!fname)	
					fname = jsl.Object.getOid(args.callee) || jsl.__mlang.function_getName.call(args.callee)
										
				params 	= jsl.__mlang.function_getParameters.call(args.callee)
				fname		= fname.indexOf(".") !== -1 ? fname.slice(fname.lastIndexOf("." + 1)) : fname
				context = cname + (cname ? "." : "") + fname + "(" + params.join(", ") + ")"
			}
			
			//StackTrace building
			//-----------------------------------------	
			if(!this.__st) this.__st = []

			this.__st.push({ 
											obj: 			typeof cx === "string" ? null 										: cx,
											method:		args && jsl.isFunction(args.callee) ? args.callee : null,  
											context: 	context, 
											params: 	params, 
											values: 	args && args.length ? Array.prototype.slice.call(args) : [] 
									 	})

			return this
		}
		catch(e) {
  		jsl.throwError(e, this, arguments)
		}
	}
 	//-------------------------------------------------------------------------------
 	jsl.Error.prototype.clearStackTrace = function() {
  	try {//@d[
  		if(!jsl.isError(this))	throw jsl.TypeError("BadMethodCall:Error")
  		if(arguments.length) 		throw jsl.ParamError()//@d]
			
			delete this.__st
			return this
  	}
  	catch(e) {
  		jsl.throwError(e, this, arguments)
  	}
  }  
	//-------------------------------------------------------------------------------
	jsl.Error.prototype.toString = function(small) {
		try {
			var msg, script, s, st, line, ch, cause, values, params, value, context, len
			//@d[
  		if(!jsl.isError(this))		throw jsl.TypeError("BadMethodCall:Error")
			if(arguments.length > 1)	throw jsl.ParamError()  		
			if(arguments.length)			jsl.validate(small, "b", "small")//@d]
			
			len			= 200
			msg			= jsl.Error.getMessage(this).replace(/^\s+|\s+$/g, "")
			script	= jsl.Error.getScriptName(this)
			st 			= jsl.Error.getStackTrace(this)			
			s				= jsl.Object.getName(this) + (msg ? ": " + msg : "")
													
			if(script) {
				s += "\n  at script \"" + script + "\""
				
				line 	= jsl.Error.getLineNumber(this)
				ch		= jsl.Error.getCharNumber(this)
				
				if(line)				s += ", line: " 			+ line
				if(line && ch)	s += ", character: "	+ ch
			}
			
			if(st.length && !small) 
				for(var a = 0; a < st.length; a++) {

					params = st[a].params
					values = st[a].values
					
					if(values.length) {
					
						context	= st[a].context.match(/[^\(]*\(/)[0]
						
						for(var b = 0; b < values.length; b++) {
							
							//1° - function
							if(jsl.isFunction(values[b]))			value = (jsl.Function || jsl.Object).getName(values[b]) + "()"
							
							//2° - error
							else if(jsl.isError(values[b]))		value = jsl.Object.getName(values[b]) 
							
							//3° - string
							else if(jsl.isString(values[b])) 	value = "\"" + values[b] + "\""
														
							//4° - array
							else if(jsl.isArray(values[b]))	{
								
								value = "[ "
									
								for(var c = 0; c < values[b].length; c++) {
									
									if(jsl.isFunction(values[b][c]))		value += (jsl.Function || jsl.Object).getName(values[b][c]) + "()"									
									else if(jsl.isError(values[b][c]))	value += jsl.Object.getName(values[b][c]) 
									else if(jsl.isString(values[b][c]))	value += "\"" + values[b][c] + "\""
									else if(jsl.isArray(values[b][c]))	value += "[...](" + values[b][c].length + ")"
									else if(jsl.isObject(values[b][c]))	value += "{...}"
									else																value += values[b][c] + ""	
																		
									if(value.length > len) 				break
									if(c < values[b].length - 1)	value += ", "																		
								}
								
								value += " ]"
							}
							else if(jsl.isRegExp(values[b]))	value = values[b] + ""
							
							//5° - object
							else if(jsl.isObject(values[b]))	{							
								
								value = "{ "
								
								jsl.Object.walk(values[b], function(id, v, last) { 
									
									value += id + ": "
									
									if(jsl.isFunction(v))			value += (jsl.Function || jsl.Object).getName(v) + "()"									
									else if(jsl.isError(v))		value += jsl.Object.getName(v) 
									else if(jsl.isString(v))	value += "\"" + v + "\""
									else if(jsl.isArray(v))		value += "[...](" + v.length + ")"
									else if(jsl.isObject(v))	value += "{...}"
									else											value += v + ""	
																	
									if(!last && value.length < len) value += ", "																		
									return value.length > len
								}) 
								
								value += " }"
							}
							
							//5° - other
							else	value = values[b] + ""
							
		          context += (params[b] || "p" + (b + 1)) + "=" + value + (b < values.length - 1 ? ", " : ")") 
							
							if(context.length > len) {
								context = context.slice(0, len) + "...)"
								break
							}          
						}
						s += "\n  at " + context.replace(/\n/g, "\\n") 
					}
					else
						s += "\n  at " + st[a].context
				}	
				
				cause = jsl.Error.getCause(this) 
				
				if(cause)
					s += "\n\nCaused By\n" + cause
								
			return s
		}
		catch(e) {
			//throw an error at this point can cause a browser freeze with infinite loops 
			//when the debug consoles is active	(ex: firebug onmouseover)	
  		return "toString() error: " + e
		}
	}
	//Error init
	//-------------------------------------------------------------------------------
	;(function() {
		
		var proto 
		
		jsl.Error.__native		= jsl.Object.__native.clone().merge(jsl.Error.prototype)
		proto									= jsl.Error.__native

		//@sys: Explorer 8.0.6 - the toString method is always not enumerable also if is setted
		proto.toString				= jsl.Error.prototype.toString
				
		//If we dont mark the name of the method, it is copied in the jsl.Error function object as
		//static method causing a 'bad number of param' error every time the object is converted 
		//into string (this + "") from the code, the toString is called from the system without params.
		proto.toString.__name = "toString"			
		
		//Data
		//-------------------------------------------------------------------------------
		proto.__message		=	undefined
    proto.__script    = undefined
    proto.__error    	= undefined
		proto.__dmessage	= undefined
		proto.__data			= undefined
		proto.__st				= []
		proto.__line			= 0
		proto.__character	= 0
		proto							= jsl.Error.prototype
		
		for(var id in proto) 
			if(proto.hasOwnProperty(id)) 
				if(id.charAt(0) !== "_" && jsl.isFunction(proto[id]) && !proto[id].__name) {
					
					jsl.Error[id] = function(obj) { 
						try {//@d[
							if(!arguments.length)	throw jsl.ParamError() 
							if(obj === null)			throw jsl.ParamError("NullValue:obj")//@d]
							
							return arguments.callee.__f.apply(obj, Array.prototype.slice.call(arguments, 1)) 
						}
						catch(e) {
							jsl.throwError(e, this, arguments)
						}
					}
					
					jsl.Error[id].__name	= id
					jsl.Error[id].__f			= proto[id]				
					proto[id].__name 			= id
				}			
	})()
	 